package com.dp.server;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import com.dp.client.dto.CiudadDTO;
import com.dp.client.dto.ConexionDTO;
import com.dp.client.dto.VueloDTO;
import com.dp.client.servicios.conexion.IServiciosConexion;
import com.dp.client.views.Geografico;
import com.dp.server.entities.Almacen;
import com.dp.server.entities.Ciudad;
import com.dp.server.entities.Conexion;
import com.dp.server.entities.Vuelo;
import com.dp.shared.FieldVerifier;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class IServiciosConexionImpl extends RemoteServiceServlet implements
		IServiciosConexion {
	final private MantenimientoGenerico<Conexion> mantenimientoGenerico = new MantenimientoGenerico<>(
			"Conexion");
	final private MantenimientoGenerico<Vuelo> mantemimientoVuelo = new MantenimientoGenerico<>(
			"Vuelo");
	final private MantenimientoGenerico<Almacen> mantenimientoAlmacen = new MantenimientoGenerico<>("Almacen");
	static int oo = 1 << 30;
    static int days [] = { Calendar.MONDAY , Calendar.TUESDAY , Calendar.WEDNESDAY , Calendar.THURSDAY , Calendar.FRIDAY , Calendar.SATURDAY , Calendar.SUNDAY };
	public List<ConexionDTO> getConexiones(String capacidadMax,
			String capacidadMin, String idOrigen, String idDestino,
			String horaMax, String horaMin, String dias) {
		int horaMinima = validData(horaMin, 0), horaMaxima = validData(horaMax,
				oo);
		int capMax = validData(capacidadMax, oo), capMin = validData(
				capacidadMin, 0);
		int idOr = validData(idOrigen, -1), idDe = validData(idDestino, -1);
		List<Conexion> lista = mantenimientoGenerico.list();
		ArrayList<ConexionDTO> result = new ArrayList<>();
		for (Conexion c : lista) {
			if (c.getCapacidad() > capMax || c.getCapacidad() < capMin)
				continue;
			if (idOr > 0 && c.getIdOrigen() != idOr)
				continue;
			if (idDe > 0 && c.getIdDestino() != idDe)
				continue;
			if (c.getHoraSalida().getHours() >= horaMinima
					&& c.getHoraSalida().getHours() <= horaMaxima) {
				boolean esta = true;
				for (int i = 0; i < c.getDiasActivos().length; i++) {
					boolean x = dias.charAt(i) == '1';
					if (x == false && c.getDiasActivos()[i]) {
						esta = false;
						break;
					}
				}
				if (esta) {
					ConexionDTO ref = new ConexionDTO(c.getId(),
							c.getIdOrigen(), c.getIdDestino(), c.getDuracion(),
							c.getCapacidad(), c.getHoraSalida(),
							c.getDescripcion(), c.getDiasActivos());
					ref.ultimaCreacionVuelos = tiempoVuelosCreados(ref.id);
					result.add(ref);
				}
			}
		}
		return result;
	}

	Date tiempoVuelosCreados(int idConexion) {
		// TODO: sacar cual es la fecha maxima en donde se tenga un vuelo. ya
		// creado.
		// si no existen vuelos creados retornar null
		Date ans = (Date) MantenimientoGenerico
				.uniqueQuery("select max(fechaHoraSalida) from Vuelo where idConexion = "
						+ idConexion);
		return ans;
	}

	int validData(String data, int def) {
		try {
			int ans = Integer.parseInt(data);
			return ans;
		} catch (Exception ex) {
		}
		return def;
	}

	@Override
	public Boolean borrarConexion(ConexionDTO conexion) {
		// TODO Auto-generated method stub
		Boolean ans = mantenimientoGenerico.eliminar(conexion.id);
		List<Vuelo> lista = (List<Vuelo>)MantenimientoGenerico.query("from Vuelo where idConexion = " + conexion.id );
		for( Vuelo v : lista ) mantemimientoVuelo.eliminar( v.getId() );
		return ans;
	}

	@Override
	public Boolean guardarNuevaConexion(ConexionDTO conexionDTO) {
		Almacen origen = mantenimientoAlmacen.buscarID( conexionDTO.idOrigen );
		Almacen destino = mantenimientoAlmacen.buscarID( conexionDTO.idDestino );
		IServiciosGeograficosImpl geo = new IServiciosGeograficosImpl();
		CiudadDTO cOrigen = geo.getCiudad( origen.getCiudadId() );
		CiudadDTO cDestino = geo.getCiudad( destino.getCiudadId() );
		conexionDTO.duracion = cOrigen.getPais().getContinente().getId() == cDestino.getPais().getContinente().getId() ? 
							    12 : 24;
		Conexion conexion = new Conexion(conexionDTO);
		Conexion ans = mantenimientoGenerico.registra(conexion);
		return ans != null;
	}

	@Override
	public Boolean generarVuelosConexion(ConexionDTO conexion, int dias) {
		// TODO Auto-generated method stub
		Date now = new Date();
		now.setHours(conexion.horaSalida.getHours());
		now.setMinutes(0);
		now.setSeconds(0);
		int j = 0;
		Date tmp = conexion.ultimaCreacionVuelos;
		if (tmp != null) {
			Date to = new Date(tmp.getTime());
			if (conexion.ultimaCreacionVuelos == null || to.getTime() - now.getTime() < -60000 ) {
				j = 0;
			} else {
				now = to;
				j = 1;
			}
		}
		now.setMinutes(0);
		now.setSeconds(0);
		now = new Date( ( now.getTime() / 1000 ) * 1000 );
		crearVuelos(conexion, now, dias, j);
		Boolean ans = true;
		return ans;
	}
	/*
	 * Fecha sin milis , dias a crear , j : offset , conexion conexion a crear
	 */
	public void crearVuelos( ConexionDTO conexion , Date now , int dias , int j ){
		List< Vuelo > vuelos = new ArrayList<>();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime( now );
		VueloDTO vuelo = new VueloDTO();
		vuelo.duracion = conexion.duracion;
		vuelo.id = 0;
		vuelo.idConexion = conexion.id;
		vuelo.idOrigen = conexion.idOrigen;
		vuelo.idDestino = conexion.idDestino;
		vuelo.capacidad = conexion.capacidad;
		int creados = dias;
		for (int i = 0; i < dias * 7 && creados > 0  ; i++ , j++ , calendar.add( Calendar.DAY_OF_WEEK , 1 ) ) {
			Date fly = calendar.getTime();
			int day =  ( fly.getDay() - 1 + 7 ) % 7;
			if( conexion.diasActivos [ day ] == false ) continue;
			vuelo.fechaHoraSalida = fly;
			Vuelo entity = new Vuelo(vuelo);
			vuelos.add( entity );
			creados--;
			//mantemimientoVuelo.registra(entity);
		}
		mantemimientoVuelo.registrarBatch( vuelos , 50 );
	}
	
	int getIdDays( int val ){
		for( int i = 0 ; i < days.length ; i++ ) if( val == days[ i ] ) return i;
		return -1;
	}
	
	//Vuelos
	@Override
	public List<VueloDTO> listVuelos(){
		List <Vuelo> vuelos=mantemimientoVuelo.list();
		ArrayList <VueloDTO> result= new ArrayList<>();
		for(Vuelo v:vuelos){
			result.add(v.extractDTO());
		}
	return result;
	}
	@Override 
	public VueloDTO buscarVuelo(int idVuelo){
		return mantemimientoVuelo.buscarID(idVuelo).extractDTO();
	}
}
